/*
 * Copyright (C) Francisco Morero Peyrona. All rights reserved.
 *
 * This software is published under the terms of Open Source
 * License version 1.1, a copy of which has been included with this
 * distribution in the License.txt file.
 */

package jdbcmanager.swing.text;

import java.util.*;

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.text.*;

import jdbcmanager.dbtools.*;
import jdbcmanager.swing.*;

/**
 * A JxSQLCodePane and a JToolBar in a BorderLayout.
 * 
 * @author Francisco Morero Peyrona
 */

public class JSQLCodeEditor extends JPanel
{
	private EditorBar     toolbar;
	private JxSQLCodePane txtEditor;

	//-------------------------------------------------------------------------//

	/**
	 * Class constructor
	 */
	public JSQLCodeEditor()
	{
		this.txtEditor = new JxSQLCodePane();
		this.toolbar   = new EditorBar();

		init();
	}

	/**
	 * Adds passed component to the tool bar.
	 * 
	 * @param action Action to add
	 */
	public void add2ToolBar( JComponent comp )
	{
		this.toolbar.add( comp );
	}

	/**
	 * Adds passed action to the tool bar. If the action ==<code>null</code> a separator is added.
	 * 
	 * @param action Action to add or <code>null</code> to add a separator.
	 */
	public void add2ToolBar( Action action )
	{
		if( action == null )
			this.toolbar.addSeparator();
		else
			this.toolbar.add( action );
	}

	/**
	 * Adds passed action to the popup.
	 * 
	 * @param action  Action to add
	 */
	public void add2Popup( Action action )
	{
		this.txtEditor.addAction2Popup( action );

		if( action instanceof JAbstractAction )
		{
			JAbstractAction act = (JAbstractAction) action;

			if( act.getKeyStroke() != null )
				this.txtEditor.addActionKeyStroke( act );
		}
	}

	/**
	 * Needed to be redeefined
	 */
	public void requestFocus()
	{
		SwingUtilities.invokeLater( new Runnable()
		{
			public void run()
			{
				JSQLCodeEditor.this.txtEditor.requestFocusInWindow();
			}
		} );
	}

	/**
	 * Set passed text as content of the SQL editor.
	 * 
	 * @param sCommand SQL command to show in the SQL editor.
	 */
	public void setText( String sCommand )
	{
		this.txtEditor.clearUndoManager();
		this.txtEditor.setText( sCommand.trim() );
		requestFocus();
	}

	/**
	 * Return the text stored in the SQL editor
	 * 
	 * @return The text stored in the SQL editor
	 */
	public String getText()
	{
		return this.txtEditor.getText().trim();
	}

	//-------------------------------------------------------------------------//

	private void init()
	{
		setLayout( new BorderLayout() );

		add( this.toolbar, BorderLayout.NORTH );
		add( new JScrollPane( this.txtEditor ), BorderLayout.CENTER );
	}

	//-------------------------------------------------------------------------//
	// INNER CLASS: the toolbar
	//-------------------------------------------------------------------------//
	private final class EditorBar extends JToolBar
	{
		private JComboBox   cmbTemplate;
		private JButton     btnFunction;
		private JxPopupMenu mnuFuncs;

		//-------------------------------------------------------------------------//

		private EditorBar()
		{
			// SQL templates combo box --------------------------------
			String[] asSqlTemplate = { "Select", "Insert", "Delete", "Update" };

			this.cmbTemplate = new JComboBox( asSqlTemplate );
			this.cmbTemplate.setMaximumSize( this.cmbTemplate.getPreferredSize() );
			this.cmbTemplate.setToolTipText( "Insert selected SQL command template into editor" );
			this.cmbTemplate.addActionListener( new ActionListener()
				{
					public void actionPerformed( ActionEvent evt )
					{
						onTemplate();
					}
				} );

			add( new JLabel( "Template " ) );
			add( this.cmbTemplate );
			addSeparator();

			// DBMS Prebuilt Functions --------------------------------
			Hashtable          htFuncs  = DbUtil.getAgentDBMS().getAgentMetaData().getPrebuiltFunctions();
			InsertFunctionName listener = new InsertFunctionName();

			this.mnuFuncs = new JxPopupMenu();

			for( Enumeration e = htFuncs.keys(); e.hasMoreElements(); )
			{
				String   sLabel = (String) e.nextElement();
				JMenu    menu   = new JMenu( sLabel );
				String[] asFunc = (String[]) htFuncs.get( sLabel );

				for( int n = 0; n < asFunc.length; n++ )
				{
					JMenuItem item = new JMenuItem( asFunc[n] );
					          item.addActionListener( listener );
					menu.add( item );
				}

				menu.setEnabled( menu.getItemCount() > 0 );
				this.mnuFuncs.add( menu );
			}

			// Predefined DBMS functions ------------------------------
			this.btnFunction = new JButton( new ImageIcon( getClass().getResource( "images/tb_funcs.gif" ) ) );
			this.btnFunction.setToolTipText( "DBMS prebuilt functions" );
			this.btnFunction.addActionListener( new ActionListener()
				{
					public void actionPerformed( ActionEvent evt )
					{
						onFunctions();
					}
				} );

			add( this.btnFunction );
			addSeparator();

			// Basic edit actions ------------------------------------
			Action[] aactBasic = JSQLCodeEditor.this.txtEditor.getBasicEditActions();

			for( int n = 0; n < aactBasic.length; n++ )
				add( aactBasic[n] );

			addSeparator();
		}

		private void onTemplate()
		{
			String sText = "";

			switch( this.cmbTemplate.getSelectedIndex() )
			{
				case 0:	sText = "SELECT *\n   FROM\n   WHERE";            break;
				case 1:	sText = "INSERT INTO\n   (, ,)\n   VALUES (, ,)"; break;
				case 2:	sText = "DELETE\n   FROM\n   WHERE";              break;
				case 3:	sText = "UPDATE\n   SET\n   FROM\n   WHERE";      break;
			}

			JSQLCodeEditor.this.txtEditor.setText( sText );
		}

		private void onFunctions()
		{
			this.mnuFuncs.show( this.btnFunction, 0, this.btnFunction.getHeight() );
		}
	}

	//-------------------------------------------------------------------------//
	// INNER CLASS: Event handler to insert a function name in the JxEditorPane
	//-------------------------------------------------------------------------//
	private final class InsertFunctionName implements ActionListener
	{
		public void actionPerformed( ActionEvent evt )
		{
			JMenuItem         item = (JMenuItem) evt.getSource();
			int               nPos = JSQLCodeEditor.this.txtEditor.getCaretPosition();
			SQLStyledDocument doc  = (SQLStyledDocument) JSQLCodeEditor.this.txtEditor.getDocument();

			try
			{
				doc.insertString( nPos, item.getText(), doc.getFunctionAttributeSet() );
			}
			catch( BadLocationException exc )
			{
				// Nothing to do
			}

			JSQLCodeEditor.this.requestFocus();
		}
	}
}